﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IOT
{
    /// <summary>
    /// 异步转同步指令
    /// </summary>
    public class CommandExecuter<T>:IDisposable
    {
        private IOTStateObject<T> _state;
        private IOTMessage<T> _msg;
        private ManualResetEventSlim _allDone = new ManualResetEventSlim(false);
        private byte[] _res;
        private Exception _ex;

        public CommandExecuter(IOTStateObject<T> iotStateObject,IOTMessage<T> message)
        {
            _state = iotStateObject;
            _msg = message;
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="timeOut">超时时间，单位秒</param>
        /// <returns></returns>
        public byte[] Send(int timeOut)
        {
            try
            {
                if (_state == null)
                    throw new Exception("传入IOTStateObject为空");
                if (_msg == null)
                    throw new Exception("传入消息为空");

                _msg.ReceiveCallback = RevCallback;                 //重新设置回调
                _msg.NeedReply = true;                              //必须是需要回调
                _state.SendQueue.Enqueue(_msg);

                //阻塞
                _allDone.Wait(timeOut * 1000);

                if (_ex != null)
                    throw _ex;

                if (_res == null)
                    throw new Exception("链接超时");
            }
            catch (Exception)
            {
                throw;
            }
            return _res;
        }

        /// <summary>
        /// 数据接收回调
        /// </summary>
        /// <param name="state"></param>
        /// <param name="data"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void RevCallback(IOTStateObject<T> state, Span<byte> data, object cdata)
        {
            try
            {
                Console.WriteLine("收到回复");
                _res = data.ToArray();
                _allDone.Set();
            }
            catch (Exception ex)
            {
                _ex = ex;
            }
        }

        public void Dispose()
        {
            _allDone.Dispose();
        }
    }
}
